package com.yitao.cms.service.product;

import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.skipper.base.bean.DataOutput;
import com.skipper.base.data.querydsl.PredicateBuilder;
import com.skipper.base.service.GenericEntityService;
import com.yitao.client.constant.ProductConstant;
import com.yitao.client.dto.product.ProductTaskLowerShelfDto;
import com.yitao.client.model.product.ProductInfoModel;
import com.yitao.client.model.product.ProductTaskLowerShelfModel;
import com.yitao.client.model.product.QProductTaskLowerShelfModel;
import com.yitao.cms.mapper.ProductRepository;
import com.yitao.cms.utils.BaseUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.*;

/**
 * @Date: 2019/6/27 15:32
 * @Author: Kien
 */
@Service
public class ProductTaskLowerShelfService extends GenericEntityService<ProductTaskLowerShelfModel, ProductTaskLowerShelfDto, QProductTaskLowerShelfModel> {
    @Autowired
    private ProductCmsService productCmsService;
    @Autowired
    private ProductRepository productRepository;

    public ProductTaskLowerShelfService(EntityManager entityManager) {
        super(entityManager);
    }
    BaseUtils base = BaseUtils.getInstance();

    /**
     *
     * 功能描述: 定时下架商品
     *
     * @param
     * @return
     * @auther: Kien
     * @date: 2019/6/27 15:43
     */
    @Transactional
    public DataOutput updateProductIsSale(){
        Date nowDate = new Date();
        logger.info("获取商品有效期");
        List<ProductTaskLowerShelfModel> list = repository.findAll(PredicateBuilder.conjunction()
                .and(() -> Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.UNEXECUTED.getCode())) // 未执行
                .and(() -> Q.lowerShelfTime.before(nowDate)) // 已在下架范围内的
                .and(() -> Q.isDelete.eq(false)) // 未删除的
                .get());
        List<Long> productId = new ArrayList<>();
        Map<Long, Long> map = new HashMap<>(); // 用商品id当key，商品有效表id做value
        if(!CollectionUtils.isEmpty(list)) {
            logger.info("符合下架商品有: "+ list.size() + "个");
            for(ProductTaskLowerShelfModel p: list) {
                logger.info("下架商品id为: " + p.getProductId());
                productId.add(p.getProductId()); // 商品id
                map.put(p.getProductId(), p.getId());
            }
        } else {
            logger.info("没有需要定时下架的商品");
        }
        if(!CollectionUtils.isEmpty(productId) && !CollectionUtils.isEmpty(map)) {
            List<ProductInfoModel> productByIds = productCmsService.getProductByIds(productId);
            // 判断这些商品是否已经下架
            List<Long> lowerShelfIds = new ArrayList<>(); // 用来保存已手动下架商品的商品有效期id
            List<Long> notLowerShelfIds = new ArrayList<>(); // 用来保存未下架商品的有效期id

            List<Long> notLowerShelfProductIds = new ArrayList<>(); // 未下架商品id列表

            // 遍历判断
            if(!CollectionUtils.isEmpty(productByIds)) {
                logger.info("获取商品信息");
                for(ProductInfoModel p: productByIds) {
                    if(p.getIsSale()) {
                        notLowerShelfProductIds.add(p.getId());
                        // 记录这个商品的商品有效期表id
                        notLowerShelfIds.add(map.get(p.getId())); // 未下架商品的有效期id
                    } else {
                        lowerShelfIds.add(map.get(p.getId())); // 已被手动下架商品的有效期id
                    }
                }
            }
            // 先下架所有未下架商品
            int i = 0;
            if(!CollectionUtils.isEmpty(notLowerShelfProductIds)) {
                i = productCmsService.updateProductSaleByIds(notLowerShelfProductIds, nowDate);
                productRepository.deleteAllByIdIn(notLowerShelfProductIds); // 将这些下架商品从es库删除
            }
            // 修改商品下架信息表
            if(i != 0) {
                updateExecuted(notLowerShelfIds, ProductConstant.EXECUTED_TASK_ENUM.EXECUTED.getCode(), nowDate); // 修改定时下架商品有效期相关
                updateExecuted(lowerShelfIds, ProductConstant.EXECUTED_TASK_ENUM.MANUAL_LOWER_SHELF.getCode(), null); // 如果是执行任务时发现已被手动下架，就不会存在执行时间，并且状态手动下架
            }
        }
        return new DataOutput(list);
    }

    /**
     *
     * 功能描述: 根据主键id修改执行状态
     *
     * @param ids 有效期表主键id
     * @param executedType 执行状态
     * @param date 执行时间(如果为手动下架，这个字段为空)
     * @return
     * @auther: Kien
     * @date: 2019/6/28 11:16
     */
    @Transactional
    public int updateExecuted(List<Long> ids, Integer executedType, Date date){
        repository.updateByWhere(PredicateBuilder.conjunction().and(() -> Q.id.in(ids)).get(), it -> {
            it.set(Q.executedTime, date);
            it.set(Q.implementNumber, 1); // 执行次数
            it.set(Q.isExecuted, executedType);
        });
        return 0;
    }

    /**
     *
     * 功能描述: 
     *
     * @param productId 根据商品id获取这个商品的下架时间
     * @return
     * @auther: Kien
     * @date: 2019/7/1 10:02
     */
    public ProductTaskLowerShelfModel findTaskLowerDetailByProductId(Long productId) {
        if(null == productId) {
            return null;
        }
        // 根据商品id和未执行查询
        ProductTaskLowerShelfModel productaskLowerShelf = repository.findOne(PredicateBuilder.conjunction()
                .and(() -> Q.productId.eq(productId))
                .and(() -> Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.UNEXECUTED.getCode()))
                .and(() -> Q.isDelete.eq(false))
                .get());
        if(productaskLowerShelf != null) { // 如果获取到该商品的下架信息
            return productaskLowerShelf;
        }
        // 如果根据商品id和未执行没有查到数据，可能这个商品已经下架了或者有被手动下架
        List<ProductTaskLowerShelfModel> list = repository.findAll(PredicateBuilder.conjunction()
                .and(() -> Q.productId.eq(productId))
                .and((() -> Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.EXECUTED.getCode()).or(Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.MANUAL_LOWER_SHELF.getCode()))))
//                .and(() -> Q.isDelete.eq(false))
                .get(), new OrderSpecifier<>(Order.DESC, Q.lowerShelfTime));
        if(CollectionUtils.isEmpty(list)) { // 这个商品没有设置自动下架
           return null;
        } else {
            // 遍历这个list，返回最新的一条记录
            return list.get(0);
        }
    }

    /**
     *
     * 功能描述: 
     *
     * @param lowerShelfTime 下架时间
     * @param productId 商品id
     *
     * @return
     * @auther: Kien
     * @date: 2019/7/1 15:21
     */
    @Transactional
    public int updateProductLowerShelfTime(Date lowerShelfTime, Long productId) {
        int i = 0;
        if(lowerShelfTime == null || productId == null) {
            return i;
        }
        // 根据商品id和未执行查询，该商品是否存自动下架记录
        ProductTaskLowerShelfModel productaskLowerShelf = repository.findOne(PredicateBuilder.conjunction()
                .and(() -> Q.productId.eq(productId))
                .and(() -> Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.UNEXECUTED.getCode()))
                .and(() -> Q.isDelete.eq(false))
                .get());
        if(productaskLowerShelf != null) {
            // 该商品存在自动下架，并且还未执行任务，执行update操作
            i = repository.updateByWhere(PredicateBuilder.conjunction().and(() -> Q.productId.eq(productId)).get(), it -> it.set(Q.lowerShelfTime, lowerShelfTime));
        } else {
            // 如果为空，表示这个商品没有设置过自动下架，或者自动下架任务已经执行完毕
            ProductTaskLowerShelfModel productaskLowerShelfModel = new ProductTaskLowerShelfModel();
            productaskLowerShelfModel.setProductId(productId); // 商品id
            productaskLowerShelfModel.setLowerShelfTime(lowerShelfTime); // 下架时间
            productaskLowerShelfModel.setIsExecuted(0); // 已执行次数
            productaskLowerShelfModel.setIsDelete(false);
            productaskLowerShelfModel.setCreateTime(new Date());
            ProductTaskLowerShelfModel save = repository.save(productaskLowerShelfModel);
            if(save != null) {
                i = 1;
            }
        }
        return i;

    }

    /**
     *
     * 功能描述: 将商品定时下架取消
     *
     * @param productId 商品id
     *
     * @return
     * @auther: Kien
     * @date: 2019/7/1 16:16
     */
    @Transactional
    public int updateProductLowerShelfDel(Long productId) {
        ProductTaskLowerShelfModel productaskLowerShelf = repository.findOne(PredicateBuilder.conjunction()
                .and(() -> Q.productId.eq(productId))
                .and(() -> Q.isExecuted.eq(ProductConstant.EXECUTED_TASK_ENUM.UNEXECUTED.getCode()))
                .and(() -> Q.isDelete.eq(false))
                .get());
        if(productaskLowerShelf != null) {
            return repository.updateByWhere(PredicateBuilder.conjunction()
                    .and(() -> Q.id.eq(productaskLowerShelf.getId()))
                    .get(), it -> it.set(Q.isDelete, true));
        }
        return 0;
    }
}
